package pl.skubicha.service;

import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pl.skubicha.domain.Groups;
import pl.skubicha.exceptions.EntityConstraintException;
import pl.skubicha.exceptions.GroupNotFoundException;
import pl.skubicha.repository.GroupRepository;
import pl.skubicha.response.GroupDTO;
import pl.skubicha.utils.GroupMapper;

@Service
public class GroupsRepositoryService implements GroupsService {

	private static Logger logger = Logger.getLogger( GroupsRepositoryService.class );

	@Autowired
	private GroupRepository groupRepository;

	@Transactional( readOnly = true )
	@Override
	public List< Groups > findAll() {
		logger.debug( "Wyszukuję wszystkie grupy." );
		return groupRepository.findAll();
	}

	@Transactional( readOnly = true )
	@Override
	public Page< Groups > findAll( final Pageable page ) {
		logger.debug( "Wyszukuję wszystkie grupy, stronicowanie." );
		return groupRepository.findAll( page );
	}

	@Transactional( readOnly = true )
	@Override
	public Page< Groups > findAllMatching( final String searchString, final Pageable page ) {
		logger.debug( "Wyszukuję grupę o nazwie %" + searchString + "%" );
		return groupRepository.findAllMatching( "%" + searchString + "%", page );
	}

	@Transactional( readOnly = true )
	@Override
	public Groups findById( final Integer id ) throws GroupNotFoundException {
		logger.debug( "Wyszukuję grupę o id: " + id );

		final Groups group = groupRepository.findOne( id );

		if ( group == null ) {
			logger.debug( "Nie znaleziono grupy o id: " + id );
			throw new GroupNotFoundException( "Nie znaleziono grupy o id: " + id );
		}

		return group;
	}

	@Transactional
	@Override
	public Groups create( final GroupDTO toCreate ) {
		logger.debug( "Tworzę nową grupę: " + toCreate );
		final Groups group = GroupMapper.map( toCreate );
		return groupRepository.save( group );
	}

	@Transactional( rollbackFor = GroupNotFoundException.class )
	@Override
	public Groups update( final GroupDTO updated ) throws GroupNotFoundException {

		logger.debug( "Aktualizuję grupę: " + updated );

		final Groups group = groupRepository.findOne( updated.getId() );

		if ( group == null ) {
			logger.debug( "Nie znaleziono grupy o id: " + updated.getId() );
			throw new GroupNotFoundException( "Nie znaleziono grupy o id: " + updated.getId() );
		}

		group.update( updated.getGroupName(), updated.getNumericGroupName() );

		return group;
	}

	@Transactional( rollbackFor = { GroupNotFoundException.class, EntityConstraintException.class } )
	@Override
	public Groups delete( final Integer id ) throws GroupNotFoundException, EntityConstraintException {

		logger.debug( " Usuwam grupe o id: " + id );

		final Groups deleted = groupRepository.findOne( id );

		if ( deleted == null ) {
			logger.debug( "Nie znaleziono grupy o id: " + id );
			throw new GroupNotFoundException( "Nie znaleziono grupy o id: " + id );
		}

		if ( CollectionUtils.isNotEmpty( deleted.getSubjects() ) ) {
			throw new EntityConstraintException( "Grupa " + deleted.getGroupFullName() + " posiada referencje do przedmiotów!" );
		}
		
		if ( CollectionUtils.isNotEmpty( deleted.getUsers() ) ) {
			throw new EntityConstraintException( "Grupa " + deleted.getGroupFullName() + " posiada referencje do studentów!" );
		}

		groupRepository.delete( deleted );
		return deleted;
	}

	public void setGroupRepository( final GroupRepository groupRepository ) {
		this.groupRepository = groupRepository;
	}
}
